package com.yvan.leto.server.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yvan.YvanUtil;
import com.yvan.leto.SegmentHelper;
import com.yvan.leto.server.dao.RepositoryPersistent;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Component(ConfigParserService.PARSER_PREFIX + SegmentHelper.SPRING_BOOT)
public class SpringBootParser implements IParser {

    @Autowired
    private RepositoryPersistent repositoryPersistent;

    @Override
    public String process(ParserContext context) {
        //合并所有 Resource
        List<File> resourceList = Lists.newArrayList();
        for (val relativePath : context.getSegment().getConfigFiles()) {
            resourceList.addAll(repositoryPersistent.repositoryEnvFileList(context.getEnv(), relativePath));
        }
        JsonNode jsonNode = IParser.mergeResourceContentToJsonNode(resourceList);

        //将 Yaml 格式转换为 Properties 格式
        Map<String, Object> properties = Maps.newLinkedHashMap();
        flatMap(properties, "", jsonNode);
        return YvanUtil.toJsonPretty(properties);
    }


    private void flatMap(Map<String, Object> map, String prefixField, JsonNode parent) {
        if (parent == null) {
            return;
        }
        String prefix = Strings.isNullOrEmpty(prefixField) ? prefixField : prefixField + ".";

        Iterator<String> fieldNames = parent.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            JsonNode jn = parent.get(fieldName);

            if (jn.isObject()) {
                flatMap(map, prefix + fieldName, jn);

            } else if (jn.isArray()) {
                ArrayNode arrayNode = (ArrayNode) jn;
                int index = 0;
                for (JsonNode element : arrayNode) {
                    if (element.isObject()) {
                        flatMap(map, prefix + fieldName + "[" + index + "]", element);

                    } else {
                        map.put(prefix + fieldName + "[" + index + "]", getJsonNodeValue(element));
                    }
                    index++;
                }

            } else {
                map.put(prefix + fieldName, getJsonNodeValue(jn));
            }
        }
    }

    private Object getJsonNodeValue(JsonNode jn) {
        if (jn.isNull()) {
            return "";

        } else if (jn.isBoolean()) {
            return jn.asBoolean();

        } else if (jn.isDouble() || jn.isFloat()) {
            return jn.asDouble();

        } else if (jn.isInt() || jn.isShort()) {
            return jn.asInt();

        } else if (jn.isLong()) {
            return jn.asLong();

        } else if (jn.isTextual()) {
            return jn.asText();

        }
        throw new RuntimeException("unkown nodetype:" + jn);
    }
}
